All of my programming classes in college were in C, but unfortunately I forgot most of it. I’ve been trying to re-learn, and I started with the simplest IRC bot possible.  This code simply connects to an IRC server by its IP address on port 6667, logs in, and responds to PING commands.

I start by creating a socket.

if ( (*sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {

Inet_pton is used to convert a IP address string into a number. Inet_aton would also work but there is no reason to use it as pton also supports IPV6 addresses.

if (inet_pton(AF_INET, server, &servaddr.sin_addr) <= 0) {

Connect is called to well, connect to the server.

if (connect(*sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 )

Once the bot is connected to the IRC server, you simply need to provide your user and nickname. See RFC 1459 for more details.

    my_send(sockfd, "NICK clark\r\n", debug);
    my_send(sockfd, "USER clark 8 * : Clark Clarkerson\r\n", debug);

Join a channel:

    my_send(sockfd, "JOIN #pat\r\n", debug);

Now all that is left to do read any network traffic the server sends. In particular we are looking for the PING command from the server.

        n = my_read(sockfd, recvline, debug);

        if (n > 0) {
            recvline[n] = 0;
            if (strstr(recvline, "PING") != NULL) {
                out[0] = 0;
                pos = strstr(recvline, " ")+1;
                sprintf(out, "PONG %s\r\n", pos);
                my_send(sockfd, out, debug);
            }
        }

Once I receive a PING command I generate a PONG command that includes the parameter sent with the PING command. For example if I received “PING irc.example.com”, I respond with “PONG irc.example.com”.

That’s it! The entire code is below. I will be adding some additional features in a later post.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#define MAXLINE 4096

int my_connect(char *server, unsigned int port, int *sockfd);
int my_send(int sockfd, char *out, int debug);
int my_read(int sockfd, char *recvline, int debug);

int main(int argc, char **argv) {
    int sockfd, n, debug;
    char recvline[MAXLINE+1], out[MAXLINE+1];
    char *cmd, *pos;
    char server[] = "64.150.185.111";
    debug = 1;

    if (!my_connect(server, 6667, &sockfd)) {
        printf("Failed to connect to %s.\n", server);
        exit(1);
    }

    my_send(sockfd, "NICK clark\r\n", debug);
    my_send(sockfd, "USER clark 8 * : Clark Clarkerson\r\n", debug);
    my_send(sockfd, "JOIN #pat\r\n", debug);

    while(1) {
        recvline[0] = 0;
        n = my_read(sockfd, recvline, debug);

        if (n > 0) {
            recvline[n] = 0;
            if (strstr(recvline, "PING") != NULL) {
                out[0] = 0;
                pos = strstr(recvline, " ")+1;
                sprintf(out, "PONG %s\r\n", pos);
                my_send(sockfd, out, debug);
            }
        }
    }
    exit(0);
}

int my_connect(char *server, unsigned int port, int *sockfd) {
    struct sockaddr_in servaddr;
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);

    if ( (*sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        return 0;
    }

    if (inet_pton(AF_INET, server, &servaddr.sin_addr) <= 0) {
        return 0;
    }
    if (connect(*sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 ) {
        return 0;
    }

    return 1;
}

int my_send(int sockfd, char *out, int debug) {
    if (debug) {
        printf("OUT: %s", out);
    }
    return send(sockfd, out, strlen(out), 0);
}

int my_read(int sockfd, char *recvline, int debug) {
    int n;
    n = read(sockfd, recvline, MAXLINE);
    if (n > 0 && debug) {
        printf("IN: %s", recvline);
    }
    return n;
}

Identifying Courier IMAP I/O abusers arrow-right
Next post